package com.csust.automaticteach.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.csust.automaticteach.exception.ErrorCode;
import com.csust.automaticteach.exception.ThrowUtils;
import com.csust.automaticteach.mapper.GenerateExamMapper;
import com.csust.automaticteach.model.dto.practicesituation.PracticeSituationUpdateRequest;
import com.csust.automaticteach.model.entity.Classes;
import com.csust.automaticteach.model.entity.GenerateExam;
import com.csust.automaticteach.model.entity.PracticeSituation;
import com.csust.automaticteach.model.entity.User;
import com.csust.automaticteach.model.vo.generateexam.GenerateExamPageVO;
import com.csust.automaticteach.model.vo.practicesituation.PracticeSituationVO;
import com.csust.automaticteach.service.ClassesService;
import com.csust.automaticteach.service.GenerateExamService;
import com.csust.automaticteach.service.PracticeSituationService;
import com.csust.automaticteach.mapper.PracticeSituationMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static cn.hutool.json.JSONUtil.toJsonStr;

/**
* @author 钰玟
* @description 针对表【t_practice_situation(练习情况表)】的数据库操作Service实现
* @createDate 2025-07-12 17:22:57
*/
@Service
public class PracticeSituationServiceImpl extends ServiceImpl<PracticeSituationMapper, PracticeSituation>
    implements PracticeSituationService{
    @Resource
    private ClassesService classesService;
    @Resource
    private GenerateExamMapper generateExamMapper;
    @Resource
    private GenerateExamService generateExamService;
    @Override
    public List<String> getTop3ErrorPoints(Map<String,Integer> errorPointMap) {
        if(errorPointMap != null && !errorPointMap.isEmpty()) {
            // kv 结构为  k:知识点  v: 次数
            // 使用ConcurrentHashMap避免并发问题，并根据value值逆序排序，取前三个entry的key
            return errorPointMap.entrySet().stream()
                    .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                    .limit(3)
                    .map(Map.Entry::getKey)
                    .toList();
        }
        else{
            return List.of("");
        }
    }

    @Override
    public void addErrorPoints(List<String> errorPoints, Map<String, Integer> errorPointMap) {
        // 将errorPoints中的错误点添加到errorPointMap中 （新的直接添加，已有的 次数加1） key为错误点，value为错误次数
        if (errorPoints != null && !errorPoints.isEmpty()) {
            for (String errorPoint : errorPoints) {
                if (errorPoint != null && !errorPoint.isEmpty()) {
                    errorPointMap.put(errorPoint, errorPointMap.getOrDefault(errorPoint, 0) + 1);
                }
            }
        }
    }

    @Override
    public PracticeSituationVO getPracticeSituationVO(PracticeSituation practiceSituation) {
        PracticeSituationVO practiceSituationVO = new PracticeSituationVO();
        //属性拷贝
        BeanUtil.copyProperties(practiceSituation, practiceSituationVO);
        //单独设置额外的属性
        //1.错误知识点
        String jsonErrorPoint = practiceSituation.getErrorPoint();
        ConcurrentHashMap errorPointMap = new ConcurrentHashMap();
        if(jsonErrorPoint!=null) {
            errorPointMap = JSONUtil.toBean(jsonErrorPoint, ConcurrentHashMap.class);
        }
        List<String> top3ErrorPoints = this.getTop3ErrorPoints(errorPointMap);
        String jsonTop3Points = toJsonStr(top3ErrorPoints);
        practiceSituationVO.setTop3errorPoints(jsonTop3Points);
        //2.正确题目数
        Long rightNum = (long) (practiceSituation.getTotalNum() * practiceSituation.getAccuracyRate());
        practiceSituationVO.setRightNum(rightNum);
        return practiceSituationVO;
    }
    @Override
    public PracticeSituationVO addPracticeSituation(User loginUser) {
        //实体对象
        PracticeSituation practiceSituation = new PracticeSituation();
        String title = loginUser.getUserName() + "的练习情况";
        practiceSituation.setTitle(title);
        practiceSituation.setUserId(loginUser.getId());
        practiceSituation.setAccuracyRate(0d);
        practiceSituation.setTotalNum(0L);
        boolean b = this.saveOrUpdate(practiceSituation);
        ThrowUtils.throwIf(!b, ErrorCode.OPERATION_ERROR);
        return this.getPracticeSituationVO(practiceSituation);
    }

    @Override
    public Boolean updatePracticeSituation(PracticeSituationUpdateRequest practiceSituationUpdateRequest) {
        List<String> errorPointsList = practiceSituationUpdateRequest.getErrorPointsList();
        Long totalNum = practiceSituationUpdateRequest.getTotalNum();
        Long rightNum = practiceSituationUpdateRequest.getRightNum();
        Long userId = practiceSituationUpdateRequest.getUserId();
        //获取原来的练习情况
        QueryWrapper<PracticeSituation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        PracticeSituation practiceSituation = this.getOne(queryWrapper);
        //1.修改对应的错误点map
        Map<String, Integer> errorPointsMap = JSONUtil.toBean(practiceSituation.getErrorPoint(), Map.class);
        this.addErrorPoints(errorPointsList, errorPointsMap);
        practiceSituation.setErrorPoint(toJsonStr(errorPointsMap));
        //2.修改对应的错误点数量
        Long totalNum1 = practiceSituation.getTotalNum();
        long updatedTotalNum = totalNum1 + totalNum;
        practiceSituation.setTotalNum(updatedTotalNum);
        //3.设置正确率
        Double accuracyRate = practiceSituation.getAccuracyRate() / 100 ;//转化为百分数
        long rightNum1 = (long) (totalNum1 * accuracyRate + rightNum);
        double updatedAccuracyRate =  ((double)rightNum1 / updatedTotalNum) * 100;//转化为百分数
        practiceSituation.setAccuracyRate(updatedAccuracyRate);
        //4.更新
        boolean b = this.updateById(practiceSituation);
        ThrowUtils.throwIf(!b, ErrorCode.OPERATION_ERROR);
        return BooleanUtil.isTrue(true);
    }

    @Override
    public List<GenerateExamPageVO> getExamsByClassIdWithStudent(Long classId) {
        //获取所有考试id列表
        List<Long> examIdList = classesService.getClassExamIds(classId);
        List<GenerateExam> generateExams = generateExamMapper.selectByIds(examIdList);
        return generateExamService.getGenerateExamVOList(generateExams);
    }
}




